package com.study.crypto.asn1.sm2;

import org.bouncycastle.asn1.*;

import java.security.InvalidParameterException;

/**
 *
 * 加密数据格式，见 {@code <GB-T 35276_2017_信息安全技术_SM2密码算法使用规范>} 第 7.2 章节
 * @author Songjin
 * @since 2021-02-28 23:39
 */
public class SM2Cipher extends ASN1Object {
    
    /** x分量 */
    private final ASN1Integer     xcoordinate;
    /** y分量 */
    private final ASN1Integer     ycoordinate;
    /** 杂凑值，32字节-256位 */
    private final ASN1OctetString hash;
    /** 密文 */
    private final ASN1OctetString cipherText;
    
    public SM2Cipher(ASN1Integer xcoordinate, ASN1Integer ycoordinate, ASN1OctetString hash, ASN1OctetString cipherText) {
        if (xcoordinate == null) {
            throw new InvalidParameterException("xcoordinate参数错误");
        }
        if (ycoordinate == null) {
            throw new InvalidParameterException("ycoordinate参数错误");
        }
        if (hash == null || hash.getOctets().length != 32) {
            throw new InvalidParameterException("hash参数固定为32字节-256位");
        }
        if (cipherText == null) {
            throw new InvalidParameterException("cipherText参数错误");
        }
        this.xcoordinate = xcoordinate;
        this.ycoordinate = ycoordinate;
        this.hash = hash;
        this.cipherText = cipherText;
    }
    
    public static SM2Cipher getInstance(Object o) {
        if (o instanceof SM2Cipher) {
            return (SM2Cipher)o;
        } else if (o != null) {
            return new SM2Cipher(ASN1Sequence.getInstance(o));
        }
        return null;
    }
    
    private SM2Cipher(ASN1Sequence seq) {
        this.xcoordinate = ASN1Integer.getInstance(seq.getObjectAt(0));
        this.ycoordinate = ASN1Integer.getInstance(seq.getObjectAt(1));
        this.hash = ASN1OctetString.getInstance(seq.getObjectAt(2));
        this.cipherText = ASN1OctetString.getInstance(seq.getObjectAt(3));
    }
    
    @Override
    public ASN1Primitive toASN1Primitive() {
        ASN1EncodableVector v = new ASN1EncodableVector(6);
        v.add(xcoordinate);
        v.add(ycoordinate);
        v.add(hash);
        v.add(cipherText);
        return new DERSequence(v);
    }
}
